package main

import (
	"fmt"
	"math/rand"
	"os"
	"time"
)

//channel 关闭后，接收方可以判断channel是否关闭，不会引起panic
//channel关闭后，再向channel中写入数据会panic
//channel关闭后，再次关闭channel，会panic
//关闭未初始化的channel，会panic
func chanTest() {
	ch := make(chan int)
	go func(ch chan int) {
		ch <- 1
		time.Sleep(time.Second * 1)
		close(ch)
	}(ch)
	go func() {
		i := 0
		for {
			if d, ok := <-ch; ok {
				fmt.Println(d, ok)
			} else {
				i++
				if i == 3 {
					os.Exit(1)
				}
				fmt.Println(d, ok)
			}
			time.Sleep(time.Millisecond * 500)
		}
	}()
}

func demo1F() {
	c := make(chan int, 0)
	fmt.Println(<-c)
	//一直接受不到数据，阻塞在这里，死锁
}

//同一个goroutine
func demo2F() {
	c := make(chan int, 0)
	c <- 1
	fmt.Println(<-c)
}

//向一个未初始化的chan发送值
func demo3F() {
	var c chan int
	go func() {
		c <- 1
	}()
	fmt.Println(<-c)
}

func demo3T() {
	var c chan int
	c = make(chan int, 0) //初始化
	go func() {
		c <- 1
	}()
	fmt.Println(<-c)
}

func demo4F() {
	var c chan int        //定义类型
	c = make(chan int, 0) //初始化
	go func() {
		for i := 0; i < 3; i++ {
			c <- i //传入channel数据
		}
	}()
	for v := range c {
		fmt.Println(v)
	}
}

func demo4T() {
	var c chan int
	c = make(chan int, 0)
	go func() {
		for i := 0; i < 3; i++ {
			c <- i
		}
		close(c) //或者defer close(c)
	}()
	for v := range c {
		fmt.Println(v)
	}
}

type Notifier interface {
	Send(ch chan<- int)
	Receive() <-chan int
}

type N1 struct {
	sch chan int
}

func (m *N1) Send(ch chan<- int) {
	for i := 0; i < 10; i++ {
		m.sch <- rand.Intn(100)
	}
	time.Sleep(time.Second * 5)
	ch <- 1
}

func (m *N1) Receive() <-chan int {
	return m.sch
}

func Init() *N1 {
	x := &N1{}
	x.sch = make(chan int, 10)
	return x
}

func signChanTest() chan int {
	var ch = make(chan int, 1)
	n := Init()
	go n.Send(ch)
	go func(n *N1) {
		for e := range n.Receive() {
			fmt.Println("value:", e)
		}
	}(n)
	return ch
}

var numbers = []int{1, 2, 3}

var channels = [3]chan int{
	nil,
	make(chan int),
	nil,
}

//说明非缓冲chan 必须收发双发就绪才会触发
func Run25() {
	select {
	case getChan(0) <- getNumber(0):
		fmt.Println("The first candidate case is selected.")
	case getChan(1) <- getNumber(1):
		fmt.Println("The second candidate case is selected.")
	case getChan(2) <- getNumber(2):
		fmt.Println("The third candidate case is selected")
	default:
		fmt.Println("No candidate case is selected!")
	}
}

func getNumber(i int) int {
	fmt.Printf("numbers[%d]\n", i)
	return numbers[i]
}

func getChan(i int) chan int {
	fmt.Printf("channels[%d]\n", i)
	return channels[i]
}
